package cn.lingyangwl.agile.common.security.service;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shenguangyang
 */
@Slf4j
@Service
public class RegisterPermService implements InitializingBean, ApplicationContextAware,
        ApplicationListener<ApplicationStartedEvent> {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    private ApplicationContext applicationContext;

    private static String startAppClassName;


    public static final String PERM_VALUE_NAME = "@ss.hasPermission";

    public static final String CACHE_KEY_PRE = "register_permission";

    /**
     * key: 路径, value: 权限值
     */
    private final Map<String, Set<String>> permMap = new HashMap<>();
//
//    @Resource
//    private RabbitTemplate rabbitTemplate;

    /**
     * 注册权限到缓存中
     */
    public void registerPerm() {
        String cacheKey = String.format("%s:%s", CACHE_KEY_PRE, startAppClassName.toLowerCase(Locale.ROOT));
        Set<String> perms = permMap.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
        log.info("register permission to cache, cacheKey: {}. size: {}", cacheKey, perms.size());
        redisTemplate.delete(cacheKey);
        redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(perms));

        // 发送到消息队列中
//        permMap.forEach((k, v) -> {
//            RegisterPermMQ mq = RegisterPermMQ.build(RegisterPermMQ.MsgPayload.builder().path(k).perms(v).build());
//            rabbitTemplate.convertAndSend(RegisterPermMQ.EXCHANGE, RegisterPermMQ.ROUTING_KEY, mq.toMessage());
//        });
        permMap.clear();
    }

    @Override
    public void afterPropertiesSet() {
//        Map<String, RequestMappingHandlerMapping> beansOfType = applicationContext.getBeansOfType(RequestMappingHandlerMapping.class);
//        beansOfType.values().forEach(e -> {
//            Map<RequestMappingInfo, HandlerMethod> map = e.getHandlerMethods();
//            map.keySet().forEach(info -> {
//                Set<String> perms = new HashSet<>();
//                HandlerMethod handlerMethod = map.get(info);
//
//                // 排除只能内网访问的接口
//                InnerAuth innerAuth = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), InnerAuth.class);
//                if (Objects.nonNull(innerAuth)) {
//                    return;
//                }
//
//                PreAuthorize preAuthorize = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), PreAuthorize.class);
//                if (Objects.isNull(preAuthorize)) {
//                    return;
//                }
//                String value = preAuthorize.value();
//                if (StringUtils.isNotEmpty(value)) {
//                    // value格式: @ss.hasPermission('system:user:query')
//                    if (value.trim().contains(PERM_VALUE_NAME)) {
//                        String perm = value.trim().replace(PERM_VALUE_NAME, "")
//                                .replace("('", "").replace("')", "");
//                        perms.add(perm);
//                    }
//                }
//                List<String> mappingPath = RequestMappingUtils.getMappingPath(preAuthorize, info);
//                mappingPath.forEach(path -> permMap.put(path, perms));
//            });
//        });
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
    }

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        startAppClassName = event.getSpringApplication().getMainApplicationClass().getName();
        log.info("===> startAppClassName: {}", startAppClassName);
        this.registerPerm();
    }

    public List<String> listAllPermissionValue() {
        Set<String> keys = redisTemplate.keys(CACHE_KEY_PRE + "*");
        if (Objects.isNull(keys)) {
            return Collections.emptyList();
        }
        List<String> resp = new ArrayList<>();
        keys.forEach(e -> {
            Object obj = redisTemplate.opsForValue().get(e);
            if (Objects.nonNull(obj) && obj instanceof String) {
                List<String> list = JSON.parseArray((String) obj, String.class);
                resp.addAll(list);
            }
        });
        return resp;
    }
}
